home *** CD-ROM | disk | FTP | other *** search
- #include "vmake.h"
-
- Prototype int get_filename(char *str, char *buf, int savemode);
- Prototype void commit_filename(char *buf);
- Prototype void read_script(void);
- Prototype int read_file(void);
- Prototype int write_file(void);
- Prototype void expand_filename(char *name, char *fullname);
- Prototype void go_dir(BPTR dirlock);
- Prototype BPTR xlockdir(char *path);
-
- #define LINE_LEN 78
- #define MIN_LINE 10
-
- static BPTR XSaveLock;
- static BOOL XSaveLockValid;
-
- /***********************************************************************************
- * Procedure: restorecurdir
- * Synopsis: (void)restorecurdir(); - Called at exit time if necessary
- * Purpose: Restores the original directory from where the program started
- ***********************************************************************************/
- static void restorecurdir()
- {
- if (XSaveLockValid)
- UnLock(CurrentDir(XSaveLock));
- XSaveLockValid = 0;
- }
-
- /***********************************************************************************
- * Procedure: go_dir
- * Synopsis: (void)go_dir(dirlock);
- * Purpose: Set the current directory to one specified by the given lock
- ***********************************************************************************/
- void go_dir(BPTR dirlock)
- {
- BPTR lock;
-
- if (dirlock)
- {
- if ( (lock = DupLock(dirlock)) != NULL)
- {
- if (!XSaveLockValid)
- {
- XSaveLock = CurrentDir(lock);
- XSaveLockValid = 1;
- atexit(restorecurdir);
- }
- else
- {
- UnLock(CurrentDir(lock));
- }
- }
- }
- }
-
- BPTR xlockdir(char *path)
- {
- BPTR lock;
-
- lock = Lock(path, SHARED_LOCK);
-
- /* We should check to make sure that the lock is valid */
- return(lock);
- }
-
- /***********************************************************************************
- * Procedure: get_filename
- * Synopsis: type = get_filename(str)
- * Purpose: Parse out a file descriptor and return a type for that name
- * This routine does not modify any permanent global data
- ***********************************************************************************/
- int get_filename(char *str, char *buf, int savemode)
- {
- char *p;
- int len;
-
- go_dir(global.homedir);
-
- if (*str)
- {
- /* They actually specified a name. All we need to do is replace the */
- /* current one. If they specified a '?', then we need to prompt the */
- /* user with the file requester. We try to use ASL first and then */
- /* fall back to ARP. */
- if (*str == '?')
- {
- int n;
-
- if (global.inrexx)
- /* don't put up requesters if called from rexx - just fail */
- {
- global.rexxrc = TEXT_BADPROJ; /* sort of fits the bill... */
- return 0;
- }
-
- if (global.freq == NULL) return(0);
-
- if (AslBase != NULL)
- {
- struct TagItem taglist[10];
-
- n = 0;
- taglist[n ].ti_Tag = ASL_Pattern;
- taglist[n++].ti_Data = (ULONG)global.text[CONFIG_PATTERN];
-
- taglist[n ].ti_Tag = ASL_File;
- taglist[n++].ti_Data = (ULONG)"";
-
- taglist[n ].ti_Tag = ASL_Dir;
- taglist[n++].ti_Data = (ULONG)"";
-
- taglist[n ].ti_Tag = ASL_Window;
- taglist[n++].ti_Data = (ULONG)global.window;
-
- #ifdef ASLFR_DoSaveMode
- taglist[n ].ti_Tag = ASLFR_DoSaveMode;
- taglist[n++].ti_Data = savemode;
- #endif
-
- #ifdef ASLFR_DoPatterns
- taglist[n ].ti_Tag = ASLFR_DoPatterns;
- taglist[n++].ti_Data = TRUE;
- #endif
-
- #ifdef ASLFR_RejectIcons
- taglist[n ].ti_Tag = ASLFR_RejectIcons;
- taglist[n++].ti_Data = TRUE;
- #endif
-
- #ifdef ASLFR_SleepWindow
- taglist[n ].ti_Tag = ASLFR_SleepWindow;
- taglist[n++].ti_Data = TRUE;
- #endif
-
- taglist[n ].ti_Tag = TAG_DONE;
- taglist[n++].ti_Data = 0;
-
- if (!AslRequest( (APTR)global.freq, taglist))
- return(0);
-
- }
- else
- {
- /* We must have arp.library (otherwise we wouldn't have a file */
- /* Requester structure.) */
- if (!ArpFileRequest( global.freq ))
- return(0);
- }
-
- /* Since the ASL requester and the ARP requester have the pointers to */
- /* the directory and the filename in the same place, we can use the */
- /* same code to parse both of them */
- n = strlen(global.freq->rf_Dir);
- len = strlen(global.freq->rf_File);
- if (len == 0)
- return (0); /* didn't pick a name */
- if (n > MAX_FILENAME) n = MAX_FILENAME;
- p = buf;
- memcpy(p, global.freq->rf_Dir, n);
- p += n;
-
- if ((n > 0) && (p[-1] != ':'))
- {
- *p++ = '/';
- n++;
- }
- if ((n + len) > MAX_FILENAME) len = MAX_FILENAME-n;
- strncpy(p, global.freq->rf_File, len);
- p[len] = 0;
- }
- else
- {
- /* Copy over the file name. Stop when we get to a '?' */
- int len;
- p = strchr(str, ';');
- if (p)
- len = p-str;
- else
- len = strlen(str);
- if (len > MAX_FILENAME) len = MAX_FILENAME;
- memcpy(buf, str, len);
- buf[len] = 0;
- }
- }
- else
- {
- /* default is to use existing global.filename */
- strcpy(buf, global.filename);
- }
- return(1);
- }
-
- /***********************************************************************************
- * Procedure: commit_filename
- * Synopsis: void get_filename(str)
- * Purpose: Set the global data to use a new file name (from get_filename())
- ***********************************************************************************/
- void commit_filename(char *buf)
- {
- char *p;
-
- /* Given a filename, we want to now set a current directory for the */
- /* Project. This means that we need to split the name into a directory */
- /* and file portion. We should also set the current directory. Note that */
- /* It might be the case that the dmakefile has a directory override for the */
- /* sources. This will work out fine because we will use the full path for */
- /* the dmakefile. */
- /* We want to set the symbols DIR and DMAKEFILE */
- /* Start by saving the temporary copy of the new filename. */
- strcpy(global.filename, buf);
- p = strrchr(global.filename, '/');
-
- if (p == NULL) p = strrchr(global.filename, ':');
- if (p != NULL)
- {
- char *tp;
- int c;
- BPTR dirlock;
-
- tp = p;
- /* we need to include the colon in a root directory name, then */
- /* null terminate so we can get a lock on the project directory */
- if (*tp == ':') tp += 1;
- c = *tp;
- *tp = 0;
- dirlock = xlockdir(global.filename);
- if (dirlock)
- {
- UnLock(global.homedir);
- global.homedir = dirlock;
- }
-
- *tp = c;
- Sym_Set(SYM_SCRIPT, p+1, NULL);
- }
- else
- {
- BPTR dirlock;
- dirlock = xlockdir("");
- if (dirlock)
- {
- UnLock(global.homedir);
- global.homedir = dirlock;
- }
- Sym_Set(SYM_SCRIPT, global.filename, NULL);
- }
-
- /* Now we want to update the title bar */
- if (*global.filename)
- {
- int len;
- strcpy(global.title, global.text[TEXT_PROJECT]);
- len = strlen(global.title);
- strncpy(global.title+len, Sym_Lookup(SYM_SCRIPT), MAX_TITLE-len);
- global.title[MAX_TITLE-1] = 0;
- }
- else
- {
- strcpy(global.title, global.text[TEXT_NOPROJ]);
- }
-
- SetWindowTitles(global.window, global.title, global.title2);
- }
-
-
- //***********************************************************************
- //* Procedure: expand_filename
- //* Synopsis: expand_pathname(name)
- //* Purpose: Constructs a fully expanded filename
- //* Note, we can not assume that the file exists, so it will
- //* not be possible to actually lock it. We can assume that
- //* the directory it is part of does exist. It will just
- //* return the name if the expansion fails in any way.
- //* Assumptions: Buffer for fullname is at least large enough to hold
- //* name, and at least MAX_FILENAME+1 bytes. This routine
- //* will not return more than MAX_FILENAME bytes.
- //***********************************************************************
- void expand_filename(char *name, char *fullname)
- {
- BPTR lock;
- __aligned struct FileInfoBlock fib;
- char *tail, *p;
- int pos;
- char buf[MAX_FILENAME+1];
-
- //
- // Step 1 - split out any directory information from the actual name
- //
- p = strrchr(name, '/');
- if (p == NULL) p = strrchr(name, ':');
- if (p != NULL)
- {
- //
- // There was some directory information involved
- //
- char c;
- tail = p+1;
- c = p[1];
- p[1] = 0;
- lock = Lock(name, SHARED_LOCK);
- p[1] = c;
- }
- else
- {
- //
- // No directory information involved, just the name relative to the
- // current directory
- //
- lock = Lock("", SHARED_LOCK);
- tail = name;
- }
-
- //
- // Step 2 - we have the lock on the directory and the tail part of the name
- // We want to construct a fully qualified path for the directory.
- // If for some reason the lock on the directory returned 0, we want to just
- // return the name they gave us to begin with.
- //
- if (lock == 0)
- {
- strcpy(fullname, name);
- return;
- }
-
- //
- // Step 3 - Fully qualify the directory portion into the buffer
- //
- if (DOSBase->dl_lib.lib_Version >= 36)
- {
- if (!NameFromLock(lock, buf, MAX_FILENAME))
- {
- //
- // Either the name is too long or there was something else wrong with
- // the file name, just return what they gave us as a start
- //
- UnLock(lock);
- strcpy(fullname, name);
- return;
- }
- UnLock(lock);
- pos = 0;
- }
- else
- {
- // Running under 1.3, we have to do this the old fashion way
-
- //
- // Just so we don't have to do any inserts/extra copies, we will work
- // from the end of the buffer and insert as we go
- //
- pos = MAX_FILENAME-1; // Leave room for a '/' on the end sometimes
- buf[--pos] = 0;
- while(lock != 0)
- {
- BPTR parent;
- int len;
-
- //
- // Examine the lock to get the name for it
- //
- Examine(lock, &fib);
-
- //
- // Find the parent of this directory
- //
- parent = ParentDir(lock);
- UnLock(lock);
- lock = parent;
-
- len = strlen(fib.fib_FileName);
- pos -= 1;
-
- if (len > pos)
- {
- //
- // oops, not enough room, just return the name they gave us
- //
- UnLock(lock);
- strcpy(fullname, name);
- return;
- }
- buf[pos] = lock ? '/' : ':';
- pos -= len;
- memcpy(buf+pos, fib.fib_FileName, len);
- }
- }
-
- //
- // We have the path part in the buffer and the name part in the tail
- // All that is left is to concatenate them together correctly
- //
- {
- int len;
-
- //
- // Successful, the buf holds the path for the directory. We will need
- // to add a / to the end if it doesn't end in a colon
- //
- len = strlen(buf+pos);
- if ((buf[pos+len-1] != ':') && (buf[pos+len-1] != '/'))
- {
- buf[pos+len++] = '/';
- buf[pos+len] = 0;
- }
-
- if ((len + strlen(tail)) >= MAX_FILENAME)
- {
- // Oops, it's to long, just use the name
- strcpy(fullname, name);
- }
- else
- {
- // Tack the name onto the path
- strcpy(fullname, buf+pos);
- strcpy(fullname+len, tail);
- }
- }
- return;
- }
-
-
- /***********************************************************************************
- * Procedure: read_script
- * Synopsis: read_script()
- * Purpose: Read in a config script
- ***********************************************************************************/
- void read_script()
- {
- char buf[256];
- FILE *fp;
- char *val;
- int len;
-
- go_dir(global.homedir);
-
- val = Sym_Lookup("TYPE");
- if (!*val) val = "Normal";
-
- if ((!strchr(val, '/')) && (!strchr(val, ':')))
- {
- sprintf(buf, "DCC:CONFIG/%s.DMakefile", val);
- val = buf;
- }
-
- fp = fopen(val, "r");
- if (fp == NULL)
- {
- request(1, TEXT_BADFILE, val, NULL);
- return;
- }
-
- Sym_Set(SYM_HOLD, "", NULL);
- while((len = fread(buf, 1, 255, fp)) > 0)
- {
- buf[len] = 0;
- Sym_Set(SYM_HOLD, NULL, buf);
- }
- fclose(fp);
- }
-
- /***********************************************************************************
- * Procedure: read_file
- * Synopsis: rc = read_file()
- * Purpose: Read in a dmakefile
- ***********************************************************************************/
- int read_file()
- {
- char buf[256];
-
- FILE *fp;
- int cstate, len;
- char name[64];
- char *fname;
-
- fname = Sym_Lookup(SYM_SCRIPT);
-
- go_dir(global.homedir);
-
- fp = fopen(fname, "r");
- if (fp == NULL)
- {
- request(1, TEXT_BADFILE, fname, NULL);
- return(1);
- }
- cstate = 1;
- while(cstate && (fgets(buf, 256, fp) != NULL))
- {
- int len;
- int extend;
- char *p, *val;
-
- len = strlen(buf)-1;
-
- /* Skip any blank lines */
- if (len < 2) continue;
-
- /* Ignore any comment lines (note that a # at the start of a line where the */
- /* previous line had a continuation mark is not considered a comment) */
- if (buf[0] == '#' && cstate == 1)
- {
- /* When we get to a line that says: */
- /* #### AUTOMATICALLY GENERATED - DO NOT EDIT BELOW THIS LINE */
- /* we want to just exit the loop and not gather any more lines */
- if (!memcmp(buf, "#### AUTOMATICALLY GENERATED", 28)) break;
- continue;
- }
-
- extend = 0;
- buf[len] = 0; /* Wipe out the \n */
- if (buf[len-1] == '\\')
- {
- extend = 1;
- buf[--len] = 0;
- }
-
- if (cstate == 2)
- {
- /* This was a continuation line, just append it to the */
- /* Current string. */
- Sym_Set(name, NULL, buf);
- }
- else
- {
- /* We need to parse out the name */
- p = strchr(buf, '=');
- if (p == NULL)
- {
- /* Funny line, we should issue a warning about it and just */
- /* Ignore it for now */
- }
- else
- {
- /* Parse out the name that is being assigned to */
- val = p+1;
-
- /* Remove any trailing blanks from the name */
- while(p > buf && p[-1] == ' ') p--;
- *p = 0;
- /* Skip over any leading blanks after the '=' */
- while(*val == ' ') val++;
- p = buf;
-
- /* Remove any leading blanks from the name */
- while(*p == ' ') p++;
- len = strlen(p);
-
- /* We now have p pointing to the nul terminated name and val pointing */
- /* to a null terminated substitution string for the variable */
- if (len > 63)
- {
- /* The name is too long, we should issue a warning and truncate it */
- p[63] = 0;
- }
- strcpy(name, p);
- /* We might consider looking up the name to see if this is a redefinition */
- /* For now we will be silent about it. */
- Sym_Set(name, val, NULL);
- }
- }
- cstate = 1;
- if (extend) cstate = 2;
- }
- /* Now we also want to gather in the automatically generated stuff so that */
- /* we don't have to read it in again. This would only need to be dealt with */
- /* If they actually change the type of project that we are building. This will */
- /* also have the effect of retaining any special configuration that they have */
- /* possibly created on another machine. */
- Sym_Set(SYM_HOLD, "", NULL);
- while((len = fread(buf, 1, 255, fp)) > 0)
- {
- buf[len] = 0;
- Sym_Set(SYM_HOLD, NULL, buf);
- }
- fclose(fp);
-
- go_dir(global.homedir);
- UnLock(global.workdir);
- global.workdir = xlockdir(Sym_Lookup("DIR"));
- return(0);
- }
-
- /***********************************************************************************
- * Procedure: write_file
- * Synopsis: write_file()
- * Purpose: Write out a dmake file based on the current options
- ***********************************************************************************/
- int write_file()
- {
- FILE *fp;
- char *place;
- char *name, *val;
- char *fname;
-
- go_dir(global.homedir);
-
- fname = Sym_Lookup(SYM_SCRIPT);
-
- name = Sym_Lookup("PROJECT");
- if (!*name) name = "*"; /* Force an invalid project name */
-
- while(*name)
- {
- if (strchr("#?\\/*: []{}^$&|()\"'", *name))
- {
- request(1, TEXT_BADPROJ, Sym_Lookup("PROJECT"), NULL);
- return(1);
- }
- name++;
- }
-
- if(!*fname)
- {
- request(1, TEXT_NOPROJ, NULL , NULL);
- return(1);
- }
-
- while ((fp = fopen(fname, "w")) == NULL)
- {
- struct stat stat_buf;
-
- if ( (stat(fname, &stat_buf) >= 0) &&
- (!(stat_buf.st_mode & S_IWRITE)))
- {
- /* The file exists, but is read-only. See if they want us */
- /* to check it out for them to work on */
- if (!request(0, TEXT_SCRIPTCO, fname, NULL)) return;
-
- /* We need to check the file out for them */
- exec_command(global.text[CONFIG_CO], fname);
- }
- else
- {
- request(0, TEXT_BADFILE, fname, NULL);
- return(1);
- }
-
- }
-
- place = NULL;
- while(place = Sym_Next(place, &name, &val))
- {
- int nlen, vlen;
-
- nlen = strlen(name);
- vlen = strlen(val);
-
- if (nlen + vlen < LINE_LEN)
- {
- if (fprintf(fp, "%s= %s\n", name, val) <= 0) goto ioerr;
- }
- else
- {
- if (fputs(name, fp) || fputs("= ", fp)) goto ioerr;
- nlen += 2;
- while(nlen + vlen > LINE_LEN)
- {
- /* Attempt to break the line at a space - DMAKE doesn't require */
- /* that the line end in a space, but it is easier for a person to */
- /* edit it when it works out that way. */
- nlen = LINE_LEN-nlen;
- while((nlen > MIN_LINE) && val[nlen-1] != ' ') nlen--;
-
- /* If we couldn't find a space on the line, just break it at the */
- /* target column anyways. */
- if (nlen == MIN_LINE) nlen = LINE_LEN-nlen;
-
- if (fwrite(val, nlen, 1, fp) != 1) goto ioerr;
- if (fputs("\\\n", fp)) goto ioerr;
- val += nlen;
- vlen -= nlen;
- nlen = 0;
- }
- if (fputs(val, fp) || (fputc('\n', fp) == EOF)) goto ioerr;
- }
- }
- /* Add the separator line */
- if (fputs("\n#### AUTOMATICALLY GENERATED - DO NOT EDIT BELOW THIS LINE\n", fp))
- goto ioerr;
- if (fputs(Sym_Lookup(SYM_HOLD), fp)) goto ioerr;
- fclose(fp);
-
- /* Now we need to create an icon for it */
-
- {
- struct DiskObject *dobj = NULL;
-
- if (global.oldproject)
- /* We read the project, so it may have a valid existing icon */
- dobj = GetDiskObject(fname);
- if (dobj != NULL)
- {
- int len;
- len = strlen(dobj->do_DefaultTool);
- if ((len >= 5) && (!stricmp(dobj->do_DefaultTool+len-5, "vmake")))
- ;
- else
- {
- /* Don't trust it, make a new one */
- FreeDiskObject(dobj);
- dobj = NULL;
- }
- }
- if (dobj == NULL)
- {
- dobj = GetDiskObject("DCC:Config/Default_Project");
- if (dobj != NULL)
- PutDiskObject(fname,dobj);
- }
- if (dobj != NULL)
- FreeDiskObject(dobj);
- }
- return(0);
-
- ioerr:
- request(1, TEXT_IOERR, fname, NULL);
- fclose(fp);
- return(1);
- }
-
-